# -*- coding: utf-8 -*-
import tkinter as tk
from tkinter import ttk
import traceback
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import time
import threading
import os
import multiprocessing
import configparser
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号



replaceDict={'plt.xlabel':'ax.set_xlabel',
             'plt.ylabel':'ax.set_ylabel',
             'plt.title':'ax.set_title',
             'plt.subplot':'ax=self.figure.add_subplot',
             'plt.grid':'ax.grid',
             'plt.plot':'ax.plot','plt.bar':'ax.bar','plt.legend':'ax.legend',
             'figure':'self.figure','plt.show()':''
             }
replaceTuple=tuple(replaceDict.keys())
def getPath():
    return os.path.dirname(__name__)

class MyConfigParser(configparser.ConfigParser):
    def as_dict(self):
        d=dict(self._sections)
        for k in d:
            d[k]=dict(d[k])
        return d

def getCommand(path=r'/media/hzy/文件/vmBackup/备份/calc/fourier.py'):
    f=open(path,'r',encoding='utf8')
    try:
        li=f.readlines()
    except:
        traceback.print_exc()
        f.close()
        return '',''
    
    cmd=''
    longRunningCode=''
    getLongRunningCode=False
    for i,line in enumerate(li):
        st=line.strip()
        if(line.startswith('####')):
            if(getLongRunningCode==False):
                getLongRunningCode=True
                continue
            else:
                getLongRunningCode=False
                continue
        
        if(getLongRunningCode==True):
            longRunningCode+=li[i]
            
        else:                        
            for beginSt in replaceDict.keys():
                if(st.startswith(beginSt)):
                    li[i]=li[i].replace(beginSt,replaceDict[beginSt])
                    break
                elif st.find('figure')!=-1:
                    li[i]=li[i].replace('figure','self.figure')
                    break           
            cmd+=li[i]
   
    return cmd,longRunningCode

    

    
    

class matplotlibFloatWindow(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("MatplotlibLive")
        self.wm_attributes('-topmost',1)
        
        self.figure=Figure(figsize=(5,4),dpi=100)
        
   
        self.canvasFrame=ttk.Frame(master=self)
        self.canvas=FigureCanvasTkAgg(self.figure, master=self.canvasFrame)
        self.font=('Arial',10)
        self.canvas.get_tk_widget().pack(side=tk.TOP,  # 上对齐
                            fill=tk.BOTH,  # 填充方式
                            expand=tk.YES)  # 随窗口大小调整而调整

        toolbar = NavigationToolbar2Tk(self.canvas, self)
        toolbar.update()
        self.canvas._tkcanvas.pack(side=tk.TOP,  # get_tk_widget()得到的就是_tkcanvas
                      fill=tk.BOTH,
                      expand=tk.YES)
                
        self.canvasFrame.pack(side=tk.LEFT,fill=tk.BOTH,expand=tk.YES)
        
                # 创建一个按钮,并把上面那个函数绑定过来
        self.statLabel=tk.Label(master=self,text='',height=10)
        self.statLabel.pack(expand=1,fill=tk.BOTH)
        


        controlFrame=ttk.Frame(master=self)
        self.refreshingStatusButton = ttk.Button(master=controlFrame, 
             text="暂停",command=self.stopOrContinueRefreshing)#控制是否停止的按钮
        self.refreshingStatus=True
        
        fileInputLabel=ttk.Label(master=controlFrame,text='输入文件路径')
        
        choosePathFrame=ttk.Frame(master=controlFrame)
        self.fileInputEntry=ttk.Entry(master=choosePathFrame,text='')
        self.chooseFileButton=ttk.Button(master=choosePathFrame,
                                         command=self.choosePath,text='..')
        fileInputLabel.pack()
        
        self.fileInputEntry.pack(side=tk.LEFT,expand=1,fill=tk.X)
        self.chooseFileButton.pack(side=tk.LEFT)
        choosePathFrame.pack(fill=tk.X,expand=1)
        
        
        refreshingIntervalInputLabel=ttk.Label(master=controlFrame,text='设定刷新间隔(ms):')
        
        
        self.renderingTimeLabel=ttk.Label(master=controlFrame,text='渲染时间消耗：1000 ms')
        
        self.refreshingRateEntry=ttk.Entry(master=controlFrame)
        self.refreshingRateEntry.insert(0,'2000')
        

        
        refreshingIntervalInputLabel.pack()
        self.refreshingRateEntry.pack(expand=tk.YES,fill=tk.X)
        self.renderingTimeLabel.pack()
        
        
        colorFrame=ttk.Frame(master=controlFrame)
        chooseColorButton=ttk.Button(master=colorFrame,
                                     text='选择颜色',
                                     command=self.chooseColor )
        self.showColorEntry=ttk.Entry(master=colorFrame)
        self.showColorLabel=tk.Label(master=colorFrame,text='..')
        
        self.showColorEntry.pack(side=tk.LEFT,expand=1,fill=tk.X)
        self.showColorLabel.pack(side=tk.LEFT)
        chooseColorButton.pack(side=tk.LEFT)
        colorFrame.pack()
        
        
        self.refreshingStatusButton.pack()
        
        controlFrame.pack(side=tk.LEFT)

        self.th=threading.Thread(target=self.refreshingLoop)
        self.th.setDaemon(True)
        self.th.start()

        self.times=0
        self.cmd='' # 绘图操作非耗时操作。
        self.lrcmd=''# 处理数据的耗时操作
        self.lrRunning=False# 高耗时应用未运行，可以刷新。
        self.local=locals()
        self.refresh()
        
    def choosePath(self):
        path=tk.filedialog.askopenfilename(title='选择文件',
                                           filetypes=[('Python脚本', '*.py'), ('All Files', '*')])
        if path:
            self.fileInputEntry.delete(0,tk.END)
            self.fileInputEntry.insert(0,path)
    def chooseColor(self):
##        print('hahahahahaha')
        
        import tkinter.colorchooser as cc
        color=cc.askcolor()
##        print(color[1])
        if color[1]!=None:
            self.showColorEntry.delete(0,tk.END)
            self.showColorLabel.config(bg=color[1])    
            self.showColorLabel.update()        
            self.showColorEntry.insert(0,color[1])
    def reportStatus(self,text,warning=False):#报错函数。
        if(warning==True):
            self.statLabel.config( fg='red',bg='white')
        else:
            self.statLabel.config( fg='black',bg='white')
        self.statLabel.config(text=text)
        
    def stopOrContinueRefreshing(self):
        if(self.refreshingStatus==True):
            self.refreshingStatus=False
            self.refreshingStatusButton.config(text='继续')
        else:
            self.refreshingStatus=True
            self.refreshingStatusButton.config(text='暂停')
            self.refresh() 
    
    def refreshingLoop(self):
        while(1): 
            t0=time.time()           
            path=self.fileInputEntry.get()
            if(os.path.isfile(path)):
                pass
            else:
                time.sleep(0.1)
                continue
            cmd,lrcmd=getCommand(path)
            self.cmd=cmd
            self.lrcmd=lrcmd
            if(self.lrcmd!=''):
                #(lrcmd)
                try:
                    exec(self.lrcmd)
                    self.local=locals()  
                except:
                    traceback.print_exc()
            print(time.time()-t0)
            time.sleep(2)   
                
                    


        
    def refresh(self):
        if(self.refreshingStatus==False):
            self.after(2000)
            return
        
        t0=time.time()
        self.figure.clf()
    
        try:
           
           exec(self.cmd,globals(),self.local)# 将变量传过来
           
           self.canvas.draw()
           self.canvas.flush_events()
           timeStr=self.refreshingRateEntry.get().strip()
           renderingTimeConsumption=int((time.time()-t0)*1000) #计算上次渲染的时间消耗
           self.renderingTimeLabel.config(text='本次渲染时间：%d ms'%(renderingTimeConsumption))
            
           if(timeStr.isdigit()):
               refreshingTime=int(timeStr)
               if(refreshingTime>2*renderingTimeConsumption): # 刷新时间必须大于渲染所用的时间的两倍及以上才行。
                   self.reportStatus(text='',warning=False)
                   self.after(refreshingTime+renderingTimeConsumption,self.refresh)
                    
               else:
                    
                   self.reportStatus(text='刷新间隔太短，渲染速度无法满足要求。\n刷新间隔至多为渲染时间的一半。',warning=True)
                   self.after(renderingTimeConsumption*3,self.refresh)
                   return
           else:  
               self.reportStatus(text='刷新间隔输入不合法\n正确的输入应该是整数。',warning=True)
               self.after(2000,self.refresh)
        except Exception as e:
            s=traceback.format_exc()
            
            self.reportStatus(text=s,warning=True)
            print(traceback.print_exc())
            self.after(2000,self.refresh)
       

def on_key_event(event):
    """键盘事件处理"""
    print("你按了%s" % event.key)
    key_press_handler(event, canvas, toolbar)
def _quit():
    """点击退出按钮时调用这个函数"""
    root.quit()  # 结束主循环
    root.destroy()  # 销毁窗口

def run():
    root=matplotlibFloatWindow()
# 主循环
    # 绑定上面定义的键盘事件处理函数
#     root.eval("tk::pkgconfig get fontsystem")
    root.canvas.mpl_connect('key_press_event', on_key_event)
    root.mainloop()
